using System;

namespace Grammars.Core
{
    public class Def<T> : Rule<T>
        where T : Node, new()
    {
        public T Node { get; internal set; }

        internal string Name;

        internal Def()
        {
            List = new ProductionList<T>();
        }

        public virtual bool IsNonTerminal
        {
            get { return true; }
        }

        internal ProductionList<T> List;

        public Def<T> With(Action<T> rule)
        {
            if (rule == null)
                throw new ArgumentNullException("rule");

            AddRule(rule);
            return this;
        }

        public Def<T> With(Action<ParameterList<T>> rule)
        {
            if (rule == null)
                throw new ArgumentNullException("rule");

            AddRule(rule);
            return this;
        }

        public Def<T> If(Func<T,bool> rule)
        {
            AddPredicate(rule);
            return this;
        }

        public Def<T> If(Func<bool> rule)
        {
            AddPredicate(rule);
            return this;
        }

        public static Def<T> operator %(Def<T> left, Def<T> right)
        {
            var rule = new ProductionRule<T>();
            rule.Defs.Add(right);
            return left % rule;
        }

        public static ProductionRule<T> operator +(Def<T> left, Def<T> right)
        {
            var rule = new ProductionRule<T>();
            rule.Defs.Add(left);
            rule.Defs.Add(right);
            return rule;
        }

        internal void ApplyRules()
        {
            ApplyRules(Node);
        }

        public bool CheckPredicates()
        {
            throw new NotImplementedException();
        }

        public override string ToString()
        {
            return Name;
        }
    }
}